package com.alili_tv.system.controller;

import com.alili_tv.system.common.BaseContext;
import com.alili_tv.system.common.LoginRequired;
import com.alili_tv.system.common.R;
import com.alili_tv.system.common.RedisRank;
import com.alili_tv.system.entity.Comment;
import com.alili_tv.system.entity.User;
import com.alili_tv.system.entity.Video;
import com.alili_tv.system.exception.BusinessException;
import com.alili_tv.system.service.CommentService;
import com.alili_tv.system.service.LikesService;
import com.alili_tv.system.service.UserService;
import com.alili_tv.system.service.VideoService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 评论表 前端控制器
 * </p>
 *
 * @author baomidou
 * @since 2023-03-17
 */
@RestController
@RequestMapping(value = "/comment", produces = "application/json")
public class CommentController {

    @Resource
    private CommentService commentService;

    @Resource
    private LikesService likesService;

    @Resource
    private VideoService videoService;

    @Resource
    private UserService userService;

    @Resource
    private RedisRank redisRank;


    /**
     * 根据视频id获取评论
     *
     * @param videoId   视频id
     * @param pageIndex 页索引
     * @param pageSize  页大小
     * @param isHot     是否以点赞数倒排, 否则以时间倒排
     * @return
     */
    @GetMapping("/getByVideoId/{videoId}/{pageIndex}/{pageSize}/{isHot}")
    public R<List<Comment>> getByVideoId(@PathVariable Long videoId,
                                         @PathVariable Integer pageIndex,
                                         @PathVariable Integer pageSize,
                                         @PathVariable Boolean isHot) {
        // 获取评论
        List<Comment> comments = commentService.getByVideoId(videoId, pageIndex, pageSize, isHot);

        // 判断用户是否对这些评论进行了点赞
        likesService.setIsLikesToComments(comments);

        return R.success(comments);
    }

    /**
     * 获取根评论的所有子评论
     *
     * @param parentId
     * @return
     */
    @GetMapping("/getAllSons/{parentId}")
    public R<List<Comment>> getAllSons(@PathVariable Long parentId) {
        List<Comment> comments = commentService.getByParentId(parentId);

        // 判断用户是否对这些评论进行了点赞
        likesService.setIsLikesToComments(comments);

        return R.success(comments);
    }

    /**
     * 添加评论
     *
     * @param comment
     * @return
     */
    @LoginRequired
    @PostMapping
    public R<Comment> save(@RequestBody Comment comment) {
        // 数据校验
        if (comment.getContent() == null || comment.getContent().trim().equals("")) {
            return R.error("输入不能为空");
        }
        // 获取根评论id并保存
        if (comment.getParentId() != null) {
            LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper
                    .select(Comment::getRootId)
                    .eq(Comment::getId, comment.getParentId());
            Comment one = commentService.getOne(queryWrapper);
            if (one == null) {
                comment.setRootId(comment.getParentId());
                comment.setParentId(null);
            } else {
                comment.setRootId(one.getRootId());
            }
        }
        // 保存评论
        commentService.save(comment);

        // 增加热度
        redisRank.incrScore(comment.getVideoId(), 10);
        return R.success(comment);
    }

    /**
     * 查询用户视频下的评论信息
     * @param pageIndex
     * @param pageSize
     * @param videoId
     * @return
     */
    @LoginRequired
    @GetMapping("/page")
    public R<Page<Comment>> page(Integer pageIndex, Integer pageSize,
                                 @RequestParam(required = false) Long videoId) {

        Page<Comment> page = new Page<>(pageIndex, pageSize);
        if (videoId == null) {
            // 查询用户发布的视频
            Long userId = BaseContext.getCurrentId();
            LambdaQueryWrapper<Video> videoQW = new LambdaQueryWrapper<Video>()
                    .select(Video::getId, Video::getTitle, Video::getVideoPath)
                    .eq(Video::getCreateUser, userId);
            List<Video> videoList = videoService.list(videoQW);
            // 若用户没有发布过视频直接返回
            if (videoList == null || videoList.size() == 0) {
                return R.success(page);
            }
            // 通过视频查询视频下的评论信息
            List<Long> videoIds = videoList.stream().map(Video::getId).toList();
            LambdaQueryWrapper<Comment> cmtQW = new LambdaQueryWrapper<Comment>()
                    .in(Comment::getVideoId, videoIds)
                    .orderByDesc(Comment::getCreateTime);
            commentService.page(page, cmtQW);
            // 设置视频信息
            page.getRecords().forEach(cmt -> {
                for (Video video : videoList) {
                    if (Objects.equals(cmt.getVideoId(), video.getId())) {
                        cmt.setVideo(video);
                        break;
                    }
                }
            });
        } else {
            // 查询指定的视频下的评论信息
            LambdaQueryWrapper<Comment> cmtQW = new LambdaQueryWrapper<Comment>()
                    .eq(Comment::getVideoId, videoId)
                    .orderByDesc(Comment::getCreateTime);
            commentService.page(page, cmtQW);
        }

        // 查询评论者的信息
        Set<Long> userIds = page.getRecords().stream().map(Comment::getCreateUser).collect(Collectors.toSet());
        Map<Long, User> userMap = userService.getByIds(userIds);
        page.getRecords().forEach(cmt -> {
            // 设置评论者信息
            cmt.setUser(userMap.get(cmt.getCreateUser()));
        });

        return R.success(page);
    }

    /**
     * 批量删除评论
     *
     * @param ids
     * @return
     */
    @LoginRequired
    @Transactional
    @DeleteMapping
    public R<String> remove(@RequestParam("ids") List<Long> ids) {
        if (ids == null || ids.size() == 0) {
            return R.error("请选择要删除的评论");
        }

        // 查询出评论，判断自己是否可以删除
        List<Comment> cmtList = commentService.getByIds(ids);
        if (cmtList == null || cmtList.size() == 0) {
            return R.error("没有权限");
        }

        Long userId = BaseContext.getCurrentId();

        // 收集不是自己的评论所属的视频id，用于判断评论是否在自己的视频下
        List<Long> videoIds = new ArrayList<>();
        // 收集是根评论的评论id
        List<Long> cmtRootIds = new ArrayList<>();
        cmtList.forEach(cmt -> {
            if (!Objects.equals(cmt.getCreateUser(), userId)) {
                videoIds.add(cmt.getVideoId());
            }
            if (cmt.getRootId() == null) {
                cmtRootIds.add(cmt.getId());
            }
        });
        // 判断评论是否在自己的视频下，不是，直接响应提示
        if (videoIds.size() != 0) {
            Map<Long, Video> videoMap = videoService.getByIds(ids);
            videoMap.forEach((id, video) -> {
                if (!Objects.equals(video.getCreateUser(), userId)) {
                    throw new BusinessException("没有权限");
                }
            });
        }

        // 验证完成，执行删除操作

        // 若删除的是根评论，则同时删除所有子评论
        if (cmtRootIds.size() != 0) {
            // 删除前查询子评论id，用于删除其点赞信息
            LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<Comment>()
                    .select(Comment::getId)
                    .in(Comment::getRootId, cmtRootIds);
            List<Comment> sonCmts = commentService.list(queryWrapper);
            Set<Long> sonIds = sonCmts.stream().map(Comment::getId).collect(Collectors.toSet());
            // 添加到ids中，一起删除
            ids.addAll(sonIds);
        }
        // 删除评论
        commentService.removeBatchByIds(ids);
        // 删除点赞信息
        likesService.removeByCommentIds(ids);

        return R.success("删除成功");
    }
}
